package com.liliudong.template.biz.service.sys.impl;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.liliudong.template.biz.mapper.sys.SysRoleMapper;
import com.liliudong.template.biz.service.sys.SysRoleDeptService;
import com.liliudong.template.biz.service.sys.SysRoleMenuService;
import com.liliudong.template.biz.service.sys.SysRoleService;
import com.liliudong.template.common.constant.ExMessageEnum;
import com.liliudong.template.common.constant.SecurityConst;
import com.liliudong.template.common.constant.SysRoleDataScopeEnum;
import com.liliudong.template.common.convert.sys.SysRoleConvert;
import com.liliudong.template.common.dto.sys.SysRoleAddOrUpdateDTO;
import com.liliudong.template.common.entity.sys.SysRole;
import com.liliudong.template.common.exception.BizException;
import com.liliudong.template.common.vo.PageVO;
import com.liliudong.template.common.vo.sys.SysRoleDetailVO;
import com.liliudong.template.common.vo.sys.SysRolePageVO;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * sys角色服务impl
 *
 * @author ldli5
 * @date 2024/06/19
 */
@Service
@RequiredArgsConstructor
public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole> implements SysRoleService {

	private final SysRoleDeptService sysRoleDeptService;

	private final SysRoleMenuService sysRoleMenuService;

	@Override
	public List<SysRole> listByUserIdIgnoreDataPermission(long userId) {
		return baseMapper.selectListByUserIdIgnoreDataPermission(userId);
	}

	@Override
	public Set<SysRoleDataScopeEnum> listDataScopeByUserIdIgnoreDataPermission(long userId) {
		return listByUserIdIgnoreDataPermission(userId)
				.stream()
				.map(SysRole::getDataScope)
				.collect(Collectors.toSet());
	}

	@Override
	@Transactional
	public void addOne(SysRoleAddOrUpdateDTO sysRoleAddOrUpdateDTO) {
		SysRole sysRole = SysRoleConvert.INSTANCE.dto2Entity(sysRoleAddOrUpdateDTO);
		List<Long> deptIds = sysRoleAddOrUpdateDTO.getDeptIds();
		List<Long> menuIds = sysRoleAddOrUpdateDTO.getMenuIds();
		if (Objects.equals(sysRole.getDataScope(), SysRoleDataScopeEnum.CUSTOMIZE) &&
				CollUtil.isEmpty(deptIds)) {
			throw new BizException(ExMessageEnum.DEPT_IDS_EMPTY);
		}
		// 校验角色编码是否重复
		boolean checkRolePermissionRepeat = this.checkRolePermissionSingle(sysRole.getPermission());
		if (!checkRolePermissionRepeat) {
			throw new BizException(ExMessageEnum.ROLE_PERMISSION_REPEAT);
		}
		// 保存角色信息
		this.save(sysRole);
		// 保存角色部门关联信息
		sysRoleDeptService.saveBatchWithRoleId(sysRole.getId(), deptIds);
		// 保存角色菜单关联信息
		sysRoleMenuService.saveBatchWithRoleId(sysRole.getId(), menuIds);
	}

	@Override
	@Transactional
	public void deleteById(Long id) {
		// 删除角色信息
		this.removeById(id);
		// 删除角色部门关联信息
		sysRoleDeptService.removeByRoleId(id);
		// 删除角色菜单关联信息
		sysRoleMenuService.removeByRoleId(id);
	}

	@Override
	@Transactional
	public void modifyById(Long id, SysRoleAddOrUpdateDTO sysRoleAddOrUpdateDTO) {
		SysRole newSysRole = SysRoleConvert.INSTANCE.dto2Entity(sysRoleAddOrUpdateDTO);
		newSysRole.setId(id);
		List<Long> deptIds = sysRoleAddOrUpdateDTO.getDeptIds();
		List<Long> menuIds = sysRoleAddOrUpdateDTO.getMenuIds();
		if (Objects.equals(newSysRole.getDataScope(), SysRoleDataScopeEnum.CUSTOMIZE) &&
				CollUtil.isEmpty(deptIds)) {
			throw new BizException(ExMessageEnum.DEPT_IDS_EMPTY);
		}
		// 校验角色编码是否重复
		boolean checkRolePermissionRepeat = this.checkRolePermissionSingle(newSysRole.getPermission());
		if (!checkRolePermissionRepeat) {
			throw new BizException(ExMessageEnum.ROLE_PERMISSION_REPEAT);
		}
		// 更新角色信息
		this.updateById(newSysRole);
		// 更新角色部门关联信息
		if (Objects.equals(SysRoleDataScopeEnum.CUSTOMIZE, sysRoleAddOrUpdateDTO.getDataScope())) {
			sysRoleDeptService.updateBatchWithRoleId(id, deptIds);
		} else {
			sysRoleDeptService.removeByRoleId(id);
		}
		// 更新角色菜单关联信息
		sysRoleMenuService.updateBatchWithRoleId(id, menuIds);
	}

	@Override
	public PageVO<SysRolePageVO> queryPage(Long current, Long size) {
		Page<SysRole> sysRolePage = page(
				lambdaQuery()
						.orderByDesc(SysRole::getSort, SysRole::getCreatedAt)
						.page(Page.of(current, size))
		);
		return PageVO.of(sysRolePage, SysRoleConvert.INSTANCE.entity2PageVo(sysRolePage.getRecords()));
	}

	@Override
	public SysRoleDetailVO detailById(Long id) {
		SysRole sysRole = this.getById(id);
		if (Objects.isNull(sysRole)) {
			throw new BizException(ExMessageEnum.ROLE_NOT_EXIST);
		}
		SysRoleDetailVO sysRoleDetailVO = SysRoleConvert.INSTANCE.entity2DetailVO(sysRole);
		// 角色部门
		if (sysRole.getDataScope() == SysRoleDataScopeEnum.CUSTOMIZE) {
			Set<Long> deptIds = sysRoleDeptService.listDeptIdsByRoleId(id);
			sysRoleDetailVO.setDeptIds(deptIds);
		}
		// 角色菜单
		Set<Long> menuIds;
		if (Objects.equals(sysRole.getPermission(), SecurityConst.SUPER_ADMIN_ROLE_PERMISSION)) {
			// 超级管理员具有所有的菜单
			menuIds = sysRoleMenuService.listMenuIds();
		} else {
			menuIds = sysRoleMenuService.listMenuIdsByRoleId(id);
		}
		sysRoleDetailVO.setMenuIds(menuIds);
		return sysRoleDetailVO;
	}

	/**
	 * 检查角色权限单个
	 *
	 * @param permission 权限编码
	 * @return boolean
	 */
	private boolean checkRolePermissionSingle(String permission) {
		return this.count(lambdaQuery().eq(SysRole::getPermission, permission).getWrapper()) <= 0;
	}

}
